package com.example.tijianserver.utils;

import java.util.concurrent.atomic.AtomicLong;

public class Snowflake {
    private static final long START_TIMESTAMP = 1582130000000L; // 自定义起始时间戳
    private static final long DATACENTER_ID = 1L; // 数据中心ID
    private static final long MACHINE_ID = 1L; // 机器ID
    private static final long SEQUENCE = 0L; // 序列号初始值
    private static final long SEQUENCE_BITS = 12L; // 序列号位数
    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); // 序列号最大值
    private static final long WORKER_ID_BITS = 5L; // 机器ID位数
    private static final long DATACENTER_ID_BITS = 5L; // 数据中心ID位数
    private static final long TIMESTAMP_BITS = 41L; // 时间戳位数
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS; // 机器ID位移
    private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; // 数据中心ID位移
    private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS; // 时间戳左移位移
    private AtomicLong sequence = new AtomicLong(SEQUENCE); // 序列号原子变量

    public long nextId() {
        long timestamp = System.currentTimeMillis();
        long workerId = MACHINE_ID;
        long datacenterId = DATACENTER_ID;
        long sequence = (this.sequence.incrementAndGet() & MAX_SEQUENCE) % MAX_SEQUENCE;
        if (sequence == 0) {
            timestamp = waitUntilNextMillis(timestamp);
        }
        long id = ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) |
                (datacenterId << DATACENTER_ID_SHIFT) |
                (workerId << WORKER_ID_SHIFT) |
                sequence;
        return id;
    }

    private long waitUntilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    public static void main(String[] args) {
        Snowflake snowflake = new Snowflake();
        for (int i = 0; i < 10; i++) {
            long id=snowflake.nextId()%1000000000;
            System.out.println("long"+id);
            int x= (int) id;
            System.out.println("int"+x);
        }
    }
}
